package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageBean;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
//import com.sky.socket.WebSocketServer;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
import org.aspectj.weaver.ast.Or;
import org.checkerframework.checker.units.qual.A;
import org.simpleframework.xml.Order;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private SetmealDishMapper setmealDishMapper;

    /**
     * 用户下单
     *
     * @param ordersSubmitDTO
     * @return
     */
    @Transactional
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {

        AddressBook addressBook = addressBookMapper.selectByAdminId(ordersSubmitDTO.getAddressBookId());

        //判断是否超出距离
        //判断地址能不能接单
        //拼接客户地址
        String user_address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName();
        //获得经纬度
        String url = String.format(MessageConstant.URL, user_address);
        String s = HttpClientUtil.doGet(url, null);

        JSONObject jsonObject = JSON.parseObject(s);
        JSONObject result = jsonObject.getJSONObject("result");
        JSONObject location = result.getJSONObject("location");
        String lng = location.getString("lng");
        String lat = location.getString("lat");
        String user_location = lat + "," + lng;

        //发送请求找到目标与店铺之间的距离
        String url2 = String.format(MessageConstant.URL1, user_location);
        String results = HttpClientUtil.doGet(url2, null);
        //获得结果解析出距离
        JSONObject jsonObject1 = JSON.parseObject(results);
        //如果里面是数组的话，就要用getJSONArray来取，这样才能取出json类型的数组
        JSONArray resultArray = jsonObject1.getJSONArray("result");
        if (resultArray != null && resultArray.size() > 0) {
            JSONObject resultObject = resultArray.getJSONObject(0);
            JSONObject distanceObject = resultObject.getJSONObject("distance");
            String distanceText = distanceObject.getString("text");
            int distanceValue = distanceObject.getIntValue("value");
            if (distanceValue > 5000) {
                throw new RuntimeException(String.format("目前的距离是%s，真送不到啊兄弟", distanceValue));
            }
        }


        Long userIds = BaseContext.getCurrentId();
        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.setUserId(userIds);

        //查询当前用户的购物车数据
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);

        //构造订单数据
        Orders order = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, order);
        order.setPhone(addressBook.getPhone());
        order.setAddress(addressBook.getDetail());
        order.setConsignee(addressBook.getConsignee());
        order.setNumber(String.valueOf(System.currentTimeMillis()));
        order.setUserId(userIds);
        order.setStatus(Orders.PENDING_PAYMENT);
        order.setPayStatus(Orders.UN_PAID);
        order.setOrderTime(LocalDateTime.now());

        //向订单表插入1条数据
        orderMapper.insert(order);

        //订单明细数据
        List<OrderDetail> orderDetailList = new ArrayList<>();

        for (ShoppingCart cart : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();

            BeanUtils.copyProperties(cart, orderDetail);
            orderDetail.setOrderId(order.getId());
            orderDetailList.add(orderDetail);
        }

        //向明细表插入n条数据
        orderDetailMapper.insert(orderDetailList);

        //清理购物车中的数据
        shoppingCartMapper.deleteAll();

        //封装返回结果
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(order.getId())
                .orderNumber(order.getNumber())
                .orderAmount(order.getAmount())
                .orderTime(order.getOrderTime())
                .build();

        return orderSubmitVO;
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    @Override
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Orders order = orderMapper.getByNumber(ordersPaymentDTO.getOrderNumber());
        order.setStatus(2);
        order.setPayStatus(2);
        order.setEstimatedDeliveryTime(LocalDateTime.now().plusMinutes(15));
        orderMapper.update(order);
        return new OrderPaymentVO(order.getEstimatedDeliveryTime());

//        //调用微信支付接口，生成预支付交易单
//        JSONObject jsonObject = weChatPayUtil.pay(
//                ordersPaymentDTO.getOrderNumber(), //商户订单号
//                new BigDecimal(0.01), //支付金额，单位 元
//                "苍穹外卖订单", //商品描述
//                user.getOpenid() //微信用户的openid
//        );
//
//        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
//            throw new OrderBusinessException("该订单已支付");
//        }
//
//        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
//        vo.setPackageStr(jsonObject.getString("package"));


    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    @Override
    public void paySuccess(String outTradeNo) {


    }

    /**
     * 查询历史订单信息
     *
     * @param pageDto
     * @return
     */
    @Override
    public PageBean<OrderVO> selectHistory(PageDto pageDto) {
        PageHelper.startPage(pageDto.getPage(), pageDto.getPageSize());
        //查订单主表
        Page<OrderVO> page = orderMapper.selectHistory(pageDto.getStatus());
        List<OrderVO> result = page.getResult();
        for (OrderVO orderVO : result) {
            Long id = orderVO.getId();
            //差附表
            List<OrderDetail> list = orderDetailMapper.getByOrderId(id);
            List<String> collect = list.stream().map(lis -> {
                return lis.getName() + "*" + lis.getNumber();//显示数量和名称
            }).collect(Collectors.toList());

            String join = String.join(";", collect);

            orderVO.setOrderDishes(join);//设置订单的名称

            orderVO.setOrderDetailList(list);
        }
        return new PageBean<>(page.getTotal(), page.getResult());

    }

    /**
     * 查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderVO selectDatails(Long id) {
        OrderVO orderVO = orderMapper.selectById(id);
        List<OrderDetail> byOrderId = orderDetailMapper.getByOrderId(id);
        orderVO.setOrderDetailList(byOrderId);
        return orderVO;
    }

    /**
     * 取消订单
     *
     * @param id
     * @return
     */
    @Override
    public void cancelOrder(Long id) {
        OrderVO orderVO = orderMapper.selectById(id);
        Integer status = orderVO.getStatus();
        Integer payStatus = orderVO.getPayStatus();
//        if (status == 1 || status == 2) {
//            status = 6;
//            orderMapper.update(status, 2, id, null);
//        }
//        if (status == 2 && payStatus == 1) {
//            status = 6;
//            payStatus = 2;
//            orderMapper.update(1, payStatus, id, null);
//            orderMapper.update(status, payStatus, id, null);
//        }
    }

    /**
     * 再来一单
     *
     * @param id
     */
    @Override
    public void againOne(Long id) {
        OrderVO orderVO = orderMapper.selectById(id);
        List<OrderDetail> byOrderId = orderDetailMapper.getByOrderId(id);
        for (OrderDetail orderDetail : byOrderId) {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCartMapper.insert(shoppingCart);
        }

    }

    /**
     * 后端订单搜索
     *
     * @param pageDto
     * @return
     */
    @Override
    public PageBean<OrderVO> search(PageDto pageDto) {
        PageHelper.startPage(pageDto.getPage(), pageDto.getPageSize());
        //查订单主表
        Page<OrderVO> page = orderMapper.selectHistoryByCondition(pageDto);
        List<OrderVO> result = page.getResult();
        for (OrderVO orderVO : result) {
            Long id = orderVO.getId();
            //差附表
            List<OrderDetail> list = orderDetailMapper.getByOrderId(id);
            orderVO.setOrderDetailList(list);
            //循环添加菜名
            StringBuilder stringBuilder = new StringBuilder();
            for (OrderDetail detail : list) {
                stringBuilder.append(detail.getName());
                stringBuilder.append("*" + detail.getNumber() + "\n");
            }
            orderVO.setOrderDishes(stringBuilder.toString());

        }
        return new PageBean<>(page.getTotal(), page.getResult());
    }

    /**
     * 订单数量统计
     *
     * @return
     */
    @Override
    public OrderStatisticsVO count() {
        OrderStatisticsVO orderStatisticsVO = orderMapper.count();
        return orderStatisticsVO;
    }

    /**
     * 接单
     *
     * @param id
     */
    @Override
    public void confirmOrder(Long id) {
        //判断地址能不能接单
        OrderVO orderVO = orderMapper.selectById(id);
        String address = "";
        Long userId = orderVO.getUserId();
        AddressBook addressBook = addressBookMapper.selectById(userId);
        //拼接客户地址
        String user_address = addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName();
        //获得经纬度
        String url = String.format(MessageConstant.URL, user_address);
        String s = HttpClientUtil.doGet(url, null);

        JSONObject jsonObject = JSON.parseObject(s);
        JSONObject result = jsonObject.getJSONObject("result");
        JSONObject location = result.getJSONObject("location");
        String lng = location.getString("lng");
        String lat = location.getString("lat");
        String user_location = lat + "," + lng;

        //发送请求找到目标与店铺之间的距离
        String url2 = String.format(MessageConstant.URL1, user_location);
        String results = HttpClientUtil.doGet(url2, null);
        //获得结果解析出距离
        JSONObject jsonObject1 = JSON.parseObject(results);
        //如果里面是数组的话，就要用getJSONArray来取，这样才能取出json类型的数组
        JSONArray resultArray = jsonObject1.getJSONArray("result");
        if (resultArray != null && resultArray.size() > 0) {
            JSONObject resultObject = resultArray.getJSONObject(0);
            JSONObject distanceObject = resultObject.getJSONObject("distance");
            String distanceText = distanceObject.getString("text");
            int distanceValue = distanceObject.getIntValue("value");
            if (distanceValue > 5000) {
                throw new RuntimeException(String.format("目前的距离是%s，真送不到啊兄弟", distanceValue));
            }
        }


//        HttpClientUtil.doGet()


        // HttpGet get = new HttpGet(北京市海淀区上地十街10号);
        //HttpGet get = new HttpGet("https://api.map.baidu.com/directionlite/v1/driving?origin=40.01116,116.339303&destination=39.936404,116.452562&ak=kAPvWQEdkGtxRVO3C1DcttTadSPpAprk");


        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.CONFIRMED);
        orders.setPayStatus(Orders.PAID);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 拒单
     *
     * @param id
     */
    @Override
    public void refuseOrder(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.CANCELLED);
        orders.setPayStatus(Orders.REFUND);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);

    }

    /**
     * 派单
     */
    @Override
    public void sendOrder(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        orders.setPayStatus(Orders.PAID);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 完成
     */
    @Override
    public void completeOrder(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.COMPLETED);
        orders.setPayStatus(Orders.PAID);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 商家取消订单
     *
     * @param
     */
    @Override
    public void adminCancelOrder(OrdersRejectionDTO ordersRejectionDTO) {
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersRejectionDTO, orders);
        orders.setStatus(Orders.CANCELLED);
        orders.setPayStatus(Orders.REFUND);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 商家拒绝订单
     *
     * @param ordersRejectionDTO
     */
    @Override
    public void adminRejectionOrder(OrdersRejectionDTO ordersRejectionDTO) {
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersRejectionDTO, orders);
        orders.setStatus(Orders.CANCELLED);
        orders.setPayStatus(Orders.REFUND);
        orders.setCancelTime(LocalDateTime.now());
        orderMapper.update(orders);
    }

    /**
     * 用户催单
     *
     * @param id
     */
   // @Autowired   //注入websocket的对象
        //    WebSocketServer webSocketServer;

    @Override
    public void reminder(Long id) {
        //获得订单号
        OrderVO orderVO = orderMapper.selectById(id);
        //通过websocket向管理端发消息
        //约定发送的是json格式的，所以要创建一个json对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", 2);//1来单，2催单
        jsonObject.put("orderId", id);//1来单，2催单
        jsonObject.put("content", "该用户饿死啦！" + orderVO.getNumber());//1来单，2催单

       // webSocketServer.sendToAllClient(jsonObject.toJSONString());
    }

    /**
     * 统计营业而根据时间
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnoverStatics(LocalDate begin, LocalDate end) {
        //定义两集合用 于存放日期和营业而
        List<String> dateList = new ArrayList<>();
        List<Double> turnover = new ArrayList<>();
        //定一个变量用于循环
        LocalDate fr = begin;
        while (!fr.isAfter(end)) {
            //查询的逻辑
//            DATE_FORMAT(tb.create_time, '%Y-%m-%d'),可以对数据库日期进行格式化
            Map<String, Object> map = new HashMap<>();
            //通过api获取当天日期的最小日期和最大日期
            LocalDateTime beginTime = LocalDateTime.of(fr, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(fr, LocalTime.MAX);
            map.put("beginTime", beginTime);
            map.put("endTime", endTime);
            map.put("status", Orders.CANCELLED);

            Double turnovers = orderMapper.getTurnoverByDate(map);

            //将数据揽入两个集合中（要做非空判断！）
            dateList.add(fr.toString());
            turnover.add(turnovers != null ? turnovers : 0.0);

            //日期加一
            fr = fr.plusDays(1);
            //返回对象


        }
        return TurnoverReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .turnoverList(StringUtils.join(turnover, ","))
                .build();


    }



    /**
     * 订单接口统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrdersByDate(LocalDate begin, LocalDate end) {
        //定义三个集合用于存放数据,定义三个变量
        List<String> dateList = new ArrayList<>();
        List<String> orderCountList = new ArrayList<>();
        List<String> validOrderCountList = new ArrayList<>();
        Double orderCompletionRate = 0.0;
        Integer totalOrderCount = 0;
        Integer validOrderCount = 0;

        LocalDate fr = begin;
        while (!fr.isAfter(end)) {
            //获得当日的开始结束时间
            LocalDateTime beginTime = LocalDateTime.of(fr, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(fr, LocalTime.MAX);
            //封装到一个map丢进去
            Map<String, Object> map = new HashMap<>();
            map.put("beginTime", beginTime);
            map.put("endTime", endTime);
            map.put("status", Orders.COMPLETED);
            //查询
            String dayOrder = orderMapper.selectOrderByDay(map);
            String dayUseOrder = orderMapper.selectUseOrderByDay(map);
            dateList.add(fr.toString());
            orderCountList.add(dayOrder != null ? dayOrder : " ");
            validOrderCountList.add(dayUseOrder != null ? dayUseOrder : " ");

            //更新时间
            fr = fr.plusDays(1);
        }
        //使用stream流进行操作，对于每日有效集合里的每一个数量进行了不变处理maptoint，然后用sum求和，求出其所有的值的总和
        totalOrderCount = orderCountList.stream().mapToInt(Integer::parseInt).sum();
        validOrderCount = validOrderCountList.stream().mapToInt(Integer::parseInt).sum();

        //用bigdicemal
        BigDecimal validOrderCounts = BigDecimal.valueOf(validOrderCount);
        BigDecimal totalOrderCounts = BigDecimal.valueOf(totalOrderCount);
        //相处
        BigDecimal divide =
                validOrderCounts.divide(totalOrderCounts, 1, RoundingMode.HALF_UP);


        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .orderCountList(StringUtils.join(orderCountList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(divide.toBigInteger().doubleValue())
                .build();

    }

    /**
     * 获得前十
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO getTop(LocalDate begin, LocalDate end) {
        //定义两个列表
        List<String> name =new ArrayList<>();
        List<Integer> num =new ArrayList<>();
        //获得当日的开始结束时间
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);


        //封装到一个map丢进去
        Map<String, Object> map = new HashMap<>();
        map.put("beginTime", beginTime);
        map.put("endTime", endTime);

        List< Map<String, Object> > map2 = orderMapper.selectTop(map);

        for (Map<String, Object> stringIntegerMap : map2) {
            String names = (String) stringIntegerMap.get("name");
            Integer o =Integer.parseInt(stringIntegerMap.get("num").toString()) ;
            name.add(names);
           num.add(o);
        }


        return SalesTop10ReportVO.builder()
                .numberList(StringUtils.join(num, ","))
                .nameList(StringUtils.join(name, ","))
                .build();


    }
}


